package kr.pe.johnkim.waiting.mobile.service;

import kr.pe.johnkim.waiting.mobile.dao.WaitingMemberRecommendationDao;
import kr.pe.johnkim.waiting.mobile.dao.WaitingRecommendationDao;
import kr.pe.johnkim.waiting.mobile.domain.WaitingMemberRecommendation;
import kr.pe.johnkim.waiting.mobile.domain.WaitingRecommendation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : John_Kim <cale9797@gmail.com>
 * @date : 13. 6. 17.
 */
@Service
public class WaitingRecommendationServiceImpl implements WaitingRecommendationService {

    // SLF4J Logging
    private Logger logger = LoggerFactory.getLogger(WaitingRecommendationServiceImpl.class);

    @Autowired
    private WaitingRecommendationDao waitingRecommendationDao;

    @Autowired
    private WaitingMemberRecommendationDao waitingMemberRecommendationDao;

    /**
     * 사용자의 추천 중복을 확인 한다.
     *
     * @param waitingRecommendation
     * @return
     */
    @Override
    public WaitingRecommendation selectDuplicationRecommendation(WaitingRecommendation waitingRecommendation) {
        logger.info("selectDuplicationRecommendation");
        return this.waitingRecommendationDao.selectDuplicationRecommendation(waitingRecommendation);
    }

    /**
     * 추천을 등록 한다.
     *
     * @param waitingRecommendation
     */
    @Override
    public void registerRecommendation(WaitingRecommendation waitingRecommendation) {
        logger.info("registerRecommendation");

        /*
        1. recommendation 테이블에 추천을 등록 한다.
        2. member recommendation 테이블에 추천 이력을 등록 한다.
        * */

        logger.info("추천 등록.");
        logger.info("> merchantId        : {}", waitingRecommendation.getMerchantId());
        logger.info("> creator           : {}", waitingRecommendation.getCreator());
        logger.info("> totalMember       : {}", waitingRecommendation.getTotalMember());
        logger.info("> totalEvaluation   : {}", waitingRecommendation.getTotalEvaluation());
        logger.info("> averageEvaluation : {}", waitingRecommendation.getAverageEvaluation());
        logger.info("> activateYn        : {}", waitingRecommendation.getActivateYn());
        logger.info("> modifyDate        : {}", waitingRecommendation.getModifyDate());
        logger.info("> registerDate      : {}", waitingRecommendation.getRegisterDate());

        // recommendation 테이블에 추천 등록.
        this.waitingRecommendationDao.registerRecommendation(waitingRecommendation);

        // 방금 등록한 추천 정보를 가져 온다.
        WaitingRecommendation result = this.waitingRecommendationDao.selectRecentRecommendationInformation(waitingRecommendation);

        logger.info("방금 등록한 추천 정보를 가져 온다.");
        logger.info("> idRecommendation : {}", result.getIdRecommendation());

        // member recommendation 테이블에 추천 이력 등록.
        WaitingMemberRecommendation memberRecommendation = new WaitingMemberRecommendation();

        memberRecommendation.setMemberId(waitingRecommendation.getMemberId());
        memberRecommendation.setEvaluation(waitingRecommendation.getEvaluation());
        memberRecommendation.setContent(waitingRecommendation.getContent());
        memberRecommendation.setActivateYn(waitingRecommendation.getActivateYn());
        memberRecommendation.setModifyDate(waitingRecommendation.getModifyDate());
        memberRecommendation.setRegisterDate(waitingRecommendation.getRegisterDate());
        memberRecommendation.setRecommendationIdRecommendation(result.getIdRecommendation());
        memberRecommendation.setRecommendationMerchantId(waitingRecommendation.getMerchantId());

        logger.info("추천 이력 등록.");
        logger.info("> memberId                       : {}", memberRecommendation.getMemberId());
        logger.info("> evaluation                     : {}", memberRecommendation.getEvaluation());
        logger.info("> content                        : {}", memberRecommendation.getContent());
        logger.info("> activateYn                     : {}", memberRecommendation.getActivateYn());
        logger.info("> modifyDate                     : {}", memberRecommendation.getModifyDate());
        logger.info("> registerDate                   : {}", memberRecommendation.getRegisterDate());
        logger.info("> recommendationIdRecommendation : {}", memberRecommendation.getRecommendationIdRecommendation());
        logger.info("> recommendationMerchantId       : {}", waitingRecommendation.getMerchantId());

        this.waitingMemberRecommendationDao.registerMemberRecommendation(memberRecommendation);
    }

    /**
     * 추천 정보를 업데이트 한다.
     *
     * @param waitingRecommendation
     */
    @Override
    public void updateRecommendation(WaitingRecommendation waitingRecommendation) {
        logger.info("updateRecommendation");

        logger.info("추천 정보를 가져 온다.");
        logger.info("> merchantId : {}", waitingRecommendation.getMerchantId());
        logger.info("> activateYn : {}", waitingRecommendation.getActivateYn());

        // 추천 정보를 가져 온다.
        WaitingRecommendation recommendation = this.waitingRecommendationDao.selectRecommendationInformation(waitingRecommendation);

        logger.info("기존 정보.");
        logger.info("> totalMember       : {}", recommendation.getTotalMember());
        logger.info("> totalEvaluation   : {}", recommendation.getTotalEvaluation());
        logger.info("> averageEvaluation : {}", recommendation.getAverageEvaluation());

        // 현재까지의 추천 점수 총 합.
        double totalEvaluation = Double.parseDouble(recommendation.getTotalEvaluation());

        // 현재까지의 추천 사용자 총 합.
        double totalMember = Double.parseDouble(recommendation.getTotalMember());

        // 현재까지의 추천 점수 평균.
//        double averageEvaluation = Double.parseDouble(recommendation.getAverageEvaluation());

        // 추천 점수 총합을 더한다.
        totalEvaluation = totalEvaluation + Double.parseDouble(waitingRecommendation.getEvaluation());

        // 추천 사용자 총합을 더한다.
        totalMember = totalMember + 1;

        // 추천 점수 평균값을 구한다.
        double averageEvaluation = totalEvaluation / totalMember;

        WaitingRecommendation recommendationParameter = new WaitingRecommendation();

        recommendationParameter.setIdRecommendation(recommendation.getIdRecommendation());
        recommendationParameter.setMerchantId(waitingRecommendation.getMerchantId());
        recommendationParameter.setTotalMember(totalMember+"");
        recommendationParameter.setTotalEvaluation(totalEvaluation+"");
        recommendationParameter.setAverageEvaluation(averageEvaluation+"");
        recommendationParameter.setActivateYn(waitingRecommendation.getActivateYn());
        recommendationParameter.setModifyDate(waitingRecommendation.getModifyDate());

        logger.info("추천을 업데이트 한다.");
        logger.info("> idRecommendation  : {}", recommendationParameter.getIdRecommendation());
        logger.info("> merchantId        : {}", recommendationParameter.getMerchantId());
        logger.info("> totalMember       : {}", recommendationParameter.getTotalMember());
        logger.info("> totalEvaluation   : {}", recommendationParameter.getTotalEvaluation());
        logger.info("> averageEvaluation : {}", recommendationParameter.getAverageEvaluation());
        logger.info("> activateYn        : {}", recommendationParameter.getActivateYn());
        logger.info("> modifyDate        : {}", recommendationParameter.getModifyDate());

        // 추천을 업데이트 한다.
        this.waitingRecommendationDao.updateRecommendation(recommendationParameter);

        // 추천 이력을 등록 한다.
        WaitingMemberRecommendation parameter = new WaitingMemberRecommendation();

        parameter.setMemberId(waitingRecommendation.getMemberId());
        parameter.setEvaluation(waitingRecommendation.getEvaluation());
        parameter.setContent(waitingRecommendation.getContent());
        parameter.setActivateYn(waitingRecommendation.getActivateYn());
        parameter.setModifyDate(waitingRecommendation.getModifyDate());
        parameter.setRegisterDate(waitingRecommendation.getRegisterDate());
        parameter.setRecommendationIdRecommendation(recommendation.getIdRecommendation());
        parameter.setRecommendationMerchantId(waitingRecommendation.getMerchantId());

        logger.info("추천 이력을 등록 한다.");
        logger.info("> memberId                       : {}", parameter.getMemberId());
        logger.info("> evaluation                     : {}", parameter.getEvaluation());
        logger.info("> content                        : {}", parameter.getContent());
        logger.info("> activateYn                     : {}", parameter.getActivateYn());
        logger.info("> modifyDate                     : {}", parameter.getModifyDate());
        logger.info("> registerDate                   : {}", parameter.getRegisterDate());
        logger.info("> recommendationIdRecommendation : {}", parameter.getRecommendationIdRecommendation());
        logger.info("> recommendationMerchantId       : {}", parameter.getRecommendationMerchantId());

        this.waitingMemberRecommendationDao.registerMemberRecommendation(parameter);
    }

    /**
     * 추천을 비활성화 한다.
     *
     * @param waitingRecommendation
     */
    @Override
    public void updateDeactivateRecommendation(WaitingRecommendation waitingRecommendation) {
        logger.info("updateDeactivateRecommendation");
        this.waitingRecommendationDao.updateDeactivateRecommendation(waitingRecommendation);
    }

    /**
     * 검색한 가맹점들에 대한 추천 목록을 가져 온다.
     *
     * @param waitingRecommendation
     * @return
     */
    @Override
    public List<WaitingRecommendation> selectSearchRecommendationList(WaitingRecommendation waitingRecommendation) {
        logger.info("selectSearchRecommendationList");

        return this.waitingRecommendationDao.selectSearchRecommendationList(waitingRecommendation);
    }

    /**
     * 특정 가맹점에 대한 추천 정보를 가져 온다.
     *
     * @param waitingRecommendation
     * @return
     */
    @Override
    public WaitingRecommendation selectRecommendationInformation(WaitingRecommendation waitingRecommendation) {
        logger.info("selectRecommendationInformation");

        return this.waitingRecommendationDao.selectRecommendationInformation(waitingRecommendation);
    }

    /**
     * 사용자가 최초 등록한 추천을 가져 온다.
     * 추천을 최초 등록할때 호출한다.
     *
     * @param waitingRecommendation
     * @return
     */
    @Override
    public WaitingRecommendation selectRecentRecommendationInformation(WaitingRecommendation waitingRecommendation) {
        logger.info("selectRecentRecommendationInformation");
        return this.waitingRecommendationDao.selectRecentRecommendationInformation(waitingRecommendation);
    }
}
